/*
 * @brief: 
 * @Author: TzzzT
 * @Date: 2022-06-10 22:12:50
 * @LastEditTime: 2022-11-29 04:35:22
 * @LastEditors: TzzzT
 */
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_gatt_defs.h"
#include "esp_bt_main.h"
#include "esp_gatt_common_api.h"


#include "my_ble_server.h"




static const char *GATTS_TABLE_TAG = "BLE_SERVER";

uint16_t rcs_handle_table[RCS_SERV_IDX_NB]; //存放生成的table的handle的数组

typedef struct {
    uint8_t                 *prepare_buf;
    int                     prepare_len;
} prepare_type_env_t;

static prepare_type_env_t prepare_write_env;


//广播时蓝牙设备的名字
static uint8_t raw_phone_adv_data[31] = {
        /* flags */
        0x02, 0x01, 0x06,
        /* tx power*/
        0x02, 0x0a, 0xeb,
        /* device name */
        0x07, 0x09, 'R','E','C','S','E','R',
};





static uint8_t raw_phone_scan_rsp_data[] = {
        /* flags */
        0x02, 0x01, 0x06,
        /* tx power */
        0x02, 0x0a, 0xeb,
};

static esp_ble_adv_params_t adv_params = {
    .adv_int_min         = 0x20,
    .adv_int_max         = 0x40,
    .adv_type            = ADV_TYPE_IND,
    .own_addr_type       = BLE_ADDR_TYPE_PUBLIC,
    .channel_map         = ADV_CHNL_ALL,
    .adv_filter_policy   = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};

//GATT
struct gatts_profile_inst {
    esp_gatts_cb_t gatts_cb;
    uint16_t gatts_if;
    uint16_t app_id;
    uint16_t conn_id;
    // uint16_t service_handle;
    // esp_gatt_srvc_id_t service_id;
    // uint16_t char_handle;
    // esp_bt_uuid_t char_uuid;
    // esp_gatt_perm_t perm;
    // esp_gatt_char_prop_t property;
    // uint16_t descr_handle;
    // esp_bt_uuid_t descr_uuid;
};

bool is_advertising = false;

server_func_t server_fun;



static void gatts_profile_event_handler(esp_gatts_cb_event_t event,
					esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);

static struct gatts_profile_inst rcs_profile_tab[PROFILE_NUM] = {
    [PROFILE_APP_IDX] = {
        .gatts_cb = gatts_profile_event_handler,
        .gatts_if = ESP_GATT_IF_NONE,       /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
    },
};

/* Service */
/* {6E400001-B5A3-F393-E0A9-E50E24DCCA9E} */
static uint8_t uart_service_uuid[16] = {0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0,
                                          0x93, 0xf3, 0xa3, 0xb5, 0x01, 0x00, 0x40, 0x6e};
 /* {6E400002-B5A3-F393-E0A9-E50E24DCCA9E} */
static uint8_t cli2ser_char_uuid[16] = {0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0,
                                          0x93, 0xf3, 0xa3, 0xb5, 0x02, 0x00, 0x40, 0x6e};
 /* {6E400003-B5A3-F393-E0A9-E50E24DCCA9E} */
static uint8_t ser2cli_char_uuid[16] = {0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0,
                                          0x93, 0xf3, 0xa3, 0xb5, 0x03, 0x00, 0x40, 0x6e};


static const uint16_t primary_service_uuid         = ESP_GATT_UUID_PRI_SERVICE;
static const uint16_t character_declaration_uuid   = ESP_GATT_UUID_CHAR_DECLARE;
static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;

// static const uint8_t char_prop_read                =  ESP_GATT_CHAR_PROP_BIT_READ;
// static const uint8_t char_prop_write               = ESP_GATT_CHAR_PROP_BIT_WRITE;
static const uint8_t char_prop_read_write          = ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_READ;
static const uint8_t char_prop_read_write_notify   = ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_NOTIFY;
static const uint8_t rcsservice_ccc[2]      = {0x01, 0x00};
//char_value只是初始值，table里val的最大长度在h文件声明，是GATTS_DEMO_CHAR_VAL_LEN_MAX
static const uint8_t char_cli_to_ser_value[4]                 = {1,2,3,4};
static const uint8_t char_serto_dev_value[4]                 = {5,6,7,8};

/* Full Database Description - Used to add attributes into the database */
static const esp_gatts_attr_db_t gatt_db[RCS_SERV_IDX_NB] =
{
    // Service Declaration
    [IDX_RCS_SVC]        =
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ,
      sizeof(ESP_UUID_LEN_128), sizeof(uart_service_uuid), (uint8_t *)uart_service_uuid}},

    /* Characteristic Declaration */
    [IDX_CHAR_CLI_TO_SER]     =
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
      CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write}},

    /* Characteristic Value */
    [IDX_CHAR_VAL_CLI_TO_SER] =
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_128, cli2ser_char_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
      GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_cli_to_ser_value), (uint8_t *)char_cli_to_ser_value}},

    /* Characteristic Declaration */
    [IDX_CHAR_SER_TO_CLI]      =
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
      CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write_notify}},

    /* Characteristic Value */
    [IDX_CHAR_VAL_SER_TO_CLI]  =
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_128, ser2cli_char_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
      GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_serto_dev_value), (uint8_t *)char_serto_dev_value}},

    /* Client Characteristic Configuration Descriptor */
    [IDX_CHAR_CFG_SER_TO_CLI]  =
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
      sizeof(uint16_t), sizeof(rcsservice_ccc), (uint8_t *)rcsservice_ccc}},
};

static void example_prepare_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param)
{
    ESP_LOGI(GATTS_TABLE_TAG, "prepare write, handle = %d, value len = %d", param->write.handle, param->write.len);
    esp_gatt_status_t status = ESP_GATT_OK;
    if (prepare_write_env->prepare_buf == NULL) {
        prepare_write_env->prepare_buf = (uint8_t *)malloc(PREPARE_BUF_MAX_SIZE * sizeof(uint8_t));
        prepare_write_env->prepare_len = 0;
        if (prepare_write_env->prepare_buf == NULL) {
            ESP_LOGE(GATTS_TABLE_TAG, "%s, Gatt_server prep no mem", __func__);
            status = ESP_GATT_NO_RESOURCES;
        }
    } else {
        if(param->write.offset > PREPARE_BUF_MAX_SIZE) {
            status = ESP_GATT_INVALID_OFFSET;
        } else if ((param->write.offset + param->write.len) > PREPARE_BUF_MAX_SIZE) {
            status = ESP_GATT_INVALID_ATTR_LEN;
        }
    }
    /*send response when param->write.need_rsp is true */
    if (param->write.need_rsp){
        esp_gatt_rsp_t *gatt_rsp = (esp_gatt_rsp_t *)malloc(sizeof(esp_gatt_rsp_t));
        if (gatt_rsp != NULL){
            gatt_rsp->attr_value.len = param->write.len;
            gatt_rsp->attr_value.handle = param->write.handle;
            gatt_rsp->attr_value.offset = param->write.offset;
            gatt_rsp->attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE;
            memcpy(gatt_rsp->attr_value.value, param->write.value, param->write.len);
            esp_err_t response_err = esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, gatt_rsp);
            if (response_err != ESP_OK){
               ESP_LOGE(GATTS_TABLE_TAG, "Send response error");
            }
            free(gatt_rsp);
        }else{
            ESP_LOGE(GATTS_TABLE_TAG, "%s, malloc failed", __func__);
        }
    }
    if (status != ESP_GATT_OK){
        return;
    }
    memcpy(prepare_write_env->prepare_buf + param->write.offset,
           param->write.value,
           param->write.len);
    prepare_write_env->prepare_len += param->write.len;

}

static void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){
    if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC && prepare_write_env->prepare_buf){
        esp_log_buffer_hex(GATTS_TABLE_TAG, prepare_write_env->prepare_buf, prepare_write_env->prepare_len);
    }else{
        ESP_LOGI(GATTS_TABLE_TAG,"ESP_GATT_PREP_WRITE_CANCEL");
    }
    if (prepare_write_env->prepare_buf) {
        free(prepare_write_env->prepare_buf);
        prepare_write_env->prepare_buf = NULL;
    }
    prepare_write_env->prepare_len = 0;
}



static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
    switch (event) {
        case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
            esp_ble_gap_start_advertising(&adv_params);
            break;
        case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT:
            break;
        case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
            /* advertising start complete event to indicate advertising start successfully or failed */
            if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
                ESP_LOGE(GATTS_TABLE_TAG, "advertising start failed");
            }else{
                ESP_LOGI(GATTS_TABLE_TAG, "advertising start successfully");
                is_advertising = true;
            }
            break;
        case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
            if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) {
                ESP_LOGE(GATTS_TABLE_TAG, "Advertising stop failed");
            }
            else {
                ESP_LOGI(GATTS_TABLE_TAG, "Stop adv successfully\n");
                is_advertising = false;
            }
            break;
        case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
            ESP_LOGI(GATTS_TABLE_TAG, "update connection params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d",
                  param->update_conn_params.status,
                  param->update_conn_params.min_int,
                  param->update_conn_params.max_int,
                  param->update_conn_params.conn_int,
                  param->update_conn_params.latency,
                  param->update_conn_params.timeout);
            break;
        default:
            break;
    }
}


//实际处理交互的函数
static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
    switch (event) {
        case ESP_GATTS_REG_EVT:{
            esp_err_t set_dev_name_ret = esp_ble_gap_set_device_name(SAMPLE_DEVICE_NAME);
            if (set_dev_name_ret){
                ESP_LOGE(GATTS_TABLE_TAG, "set device name failed, error code = %x", set_dev_name_ret);
            }else{
                ESP_LOGE(GATTS_TABLE_TAG, "set device name success");
            }

            //创建table
            esp_err_t create_attr_ret = esp_ble_gatts_create_attr_tab(gatt_db, gatts_if, RCS_SERV_IDX_NB, SVC_INST_ID);
            if (create_attr_ret){
                ESP_LOGE(GATTS_TABLE_TAG, "create attr table failed, error code = %x", create_attr_ret);
            }
            break;
        }
        case ESP_GATTS_READ_EVT:
            ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_READ_EVT");
       	    break;
        case ESP_GATTS_WRITE_EVT:
            if (!param->write.is_prep){
                // the data length of gattc write  must be less than GATTS_DEMO_CHAR_VAL_LEN_MAX.
                if (rcs_handle_table[IDX_CHAR_CFG_SER_TO_CLI] == param->write.handle && param->write.len == 2){
                    uint16_t descr_value = param->write.value[1]<<8 | param->write.value[0];
                    if (descr_value == 0x0001){
                        ESP_LOGI(GATTS_TABLE_TAG, "notify enable");
                    }else if (descr_value == 0x0002){
                        ESP_LOGI(GATTS_TABLE_TAG, "indicate enable");
                    }if (descr_value == 0x0000){
                        ESP_LOGI(GATTS_TABLE_TAG, "notify indicate disable");
                    }
                }else if (rcs_handle_table[IDX_CHAR_VAL_CLI_TO_SER] == param->write.handle){
                    server_fun.cli_write_cb(param->write.bda, param->write.value, param->write.len);
                }
                /* send response when param->write.need_rsp is true*/
                if (param->write.need_rsp){
                    ESP_LOGI(GATTS_TABLE_TAG, "write.need_rsp");
                    esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
                }
            }else{
                /* handle prepare write */
                example_prepare_write_event_env(gatts_if, &prepare_write_env, param);
            }
      	    break;
        case ESP_GATTS_EXEC_WRITE_EVT: 
            // the length of gattc prepare write data must be less than GATTS_DEMO_CHAR_VAL_LEN_MAX. 
            ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_EXEC_WRITE_EVT");
            example_exec_write_event_env(&prepare_write_env, param);
            break;
        case ESP_GATTS_MTU_EVT:
            ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_MTU_EVT, MTU %d", param->mtu.mtu);
            break;
        case ESP_GATTS_CONF_EVT:
            ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_CONF_EVT, status = %d, attr_handle %d", param->conf.status, param->conf.handle);
            break;
        case ESP_GATTS_START_EVT:
            ESP_LOGI(GATTS_TABLE_TAG, "SERVICE_START_EVT, status %d, service_handle %d", param->start.status, param->start.service_handle);
            break;
        case ESP_GATTS_CONNECT_EVT:
            ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_CONNECT_EVT, conn_id = %d", param->connect.conn_id);
            esp_ble_conn_update_params_t conn_params = {0};
            memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t));
            /* For the iOS system, please refer to Apple official documents about the BLE connection parameters restrictions. */
            conn_params.latency = 1;
            conn_params.max_int = 0x20;    // max_int = 0x20*1.25ms = 40ms
            conn_params.min_int = 0x10;    // min_int = 0x10*1.25ms = 20ms
            conn_params.timeout = 400;    // timeout = 400*10ms = 4000ms
            //start sent the update connection parameters to the peer device.
            esp_ble_gap_update_conn_params(&conn_params);
            server_fun.cli_conn_cb(param->connect.remote_bda);
            break;
        case ESP_GATTS_DISCONNECT_EVT:
            ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_DISCONNECT_EVT, reason = 0x%x", param->disconnect.reason);
            server_fun.cli_disconn_cb(param->disconnect.remote_bda);
            //esp_ble_gap_start_advertising(&adv_params);
            break;
        //创建attribute table
        case ESP_GATTS_CREAT_ATTR_TAB_EVT:{
            if (param->add_attr_tab.status != ESP_GATT_OK){
                ESP_LOGE(GATTS_TABLE_TAG, "create attribute table failed, error code=0x%x", param->add_attr_tab.status);
            }
            else if (param->add_attr_tab.num_handle != RCS_SERV_IDX_NB){
                ESP_LOGE(GATTS_TABLE_TAG, "create attribute table abnormally, num_handle (%d) \
                        doesn't equal to WIFISERV_IDX_NB(%d)", param->add_attr_tab.num_handle, RCS_SERV_IDX_NB);
            }
            else {
                ESP_LOGI(GATTS_TABLE_TAG, "create attribute table successfully, the number handle = %d\n",param->add_attr_tab.num_handle);
                memcpy(rcs_handle_table, param->add_attr_tab.handles, sizeof(rcs_handle_table));
                esp_ble_gatts_start_service(rcs_handle_table[IDX_RCS_SVC]);
            }
            break;
        }
        case ESP_GATTS_OPEN_EVT:
            ESP_LOGE(GATTS_TABLE_TAG, "ESP_GATTS_OPEN_EVT" );
            break;
        case ESP_GATTS_STOP_EVT:
        case ESP_GATTS_CANCEL_OPEN_EVT:
        case ESP_GATTS_CLOSE_EVT:
        case ESP_GATTS_LISTEN_EVT:
        case ESP_GATTS_CONGEST_EVT:
        case ESP_GATTS_UNREG_EVT:
        case ESP_GATTS_DELETE_EVT:
        default:
            break;
    }
}



static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
    /* If event is register event, store the gatts_if for each profile */
    if (event == ESP_GATTS_REG_EVT) {
        if (param->reg.status == ESP_GATT_OK) {
            rcs_profile_tab[PROFILE_APP_IDX].gatts_if = gatts_if;
        } else {
            ESP_LOGE(GATTS_TABLE_TAG, "reg app failed, app_id %04x, status %d",
                    param->reg.app_id,
                    param->reg.status);
            return;
        }
    }
    do {
        int idx;
        for (idx = 0; idx < PROFILE_NUM; idx++) {
            /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */
            if (gatts_if == ESP_GATT_IF_NONE || gatts_if == rcs_profile_tab[idx].gatts_if) {
                if (rcs_profile_tab[idx].gatts_cb) {
                    rcs_profile_tab[idx].gatts_cb(event, gatts_if, param);
                }
            }
        }
    } while (0);
}


void ble_server_init(void)
{
    esp_err_t ret;
    ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));

    //bt controller
    esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
    ret = esp_bt_controller_init(&bt_cfg);
    if (ret) {
        ESP_LOGE(GATTS_TABLE_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret));
        return;
    }
    ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
    if (ret) {
        ESP_LOGE(GATTS_TABLE_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret));
        return;
    }
    //bluedroid
    ret = esp_bluedroid_init();
    if (ret) {
        ESP_LOGE(GATTS_TABLE_TAG, "%s init bluetooth failed: %s", __func__, esp_err_to_name(ret));
        return;
    }
    ret = esp_bluedroid_enable();
    if (ret) {
        ESP_LOGE(GATTS_TABLE_TAG, "%s enable bluetooth failed: %s", __func__, esp_err_to_name(ret));
        return;
    }
    ret = esp_ble_gatts_register_callback(gatts_event_handler);
    if (ret){
        ESP_LOGE(GATTS_TABLE_TAG, "gatts register error, error code = %x", ret);
        return;
    }

    ret = esp_ble_gap_register_callback(gap_event_handler);
    if (ret){
        ESP_LOGE(GATTS_TABLE_TAG, "gap register error, error code = %x", ret);
        return;
    }
    //注册profile
    ret = esp_ble_gatts_app_register(ESP_APP_ID);
    if (ret){
        ESP_LOGE(GATTS_TABLE_TAG, "gatts app register error, error code = %x", ret);
        return;
    }
    esp_err_t local_mtu_ret = esp_ble_gatt_set_local_mtu(500);
    if (local_mtu_ret){
        ESP_LOGE(GATTS_TABLE_TAG, "set local  MTU failed, error code = %x", local_mtu_ret);
    }
}

void ble_gap_gatt_close(void){
    esp_err_t ret = esp_ble_gatts_app_unregister(rcs_profile_tab[PROFILE_APP_IDX].gatts_if);
    if (ret == ESP_OK)
    {
        ESP_LOGE(GATTS_TABLE_TAG, "close wifi-app success\n"); 
    }else
    {
        ESP_LOGE(GATTS_TABLE_TAG, "close wifi-app wrong\n"); 
    }
    ret = esp_ble_gap_stop_advertising();
    if (ret == ESP_OK)
    {
        ESP_LOGE(GATTS_TABLE_TAG, "close gap success\n"); 
    }else
    {
        ESP_LOGE(GATTS_TABLE_TAG, "close gap wrong\n"); 
    }
}

void ble_server_close(void){
    ble_gap_gatt_close();

    esp_err_t ret = esp_bluedroid_disable();
    if (ret == ESP_OK)
    {
        ESP_LOGE(GATTS_TABLE_TAG, "esp_bluedroid_disable  success\n"); 
    }else
    {
        ESP_LOGE(GATTS_TABLE_TAG, "esp_bluedroid_disable wrong, %d \n",ret); 
    }
    ret = esp_bluedroid_deinit();
    if (ret == ESP_OK)
    {
        ESP_LOGE(GATTS_TABLE_TAG, "esp_bluedroid_deinit success\n"); 
    }else
    {
        ESP_LOGE(GATTS_TABLE_TAG, "esp_bluedroid_deinit wrong, %d \n",ret); 
    }

    ret = esp_bt_controller_disable();
    if (ret == ESP_OK)
    {
        ESP_LOGE(GATTS_TABLE_TAG, "esp_bt_controller_disable  success\n"); 
    }else
    {
        ESP_LOGE(GATTS_TABLE_TAG, "esp_bt_controller_disable wrong, %d \n",ret); 
    }
    ret = esp_bt_controller_deinit();
    if (ret == ESP_OK)
    {
        ESP_LOGE(GATTS_TABLE_TAG, "esp_bt_controller_deinit success\n"); 
    }else
    {
        ESP_LOGE(GATTS_TABLE_TAG, "esp_bt_controller_deinit wrong, %d \n",ret); 
    }

    esp_bt_mem_release(ESP_BT_MODE_BLE);

}

server_func_t* get_server_func_p(void){
    return &server_fun;
}

bool is_server_advertising(void){
    return is_advertising;
}

void stop_server_advertising(void){
    is_advertising = false;
    ESP_LOGI(GATTS_TABLE_TAG, "set is_advertising false: %d", is_advertising);
    esp_ble_gap_stop_advertising();
}

esp_err_t set_adv_device_name(uint8_t* adv_dev_name,uint8_t name_len){
    if(is_advertising){
        esp_ble_gap_stop_advertising();
    }
    is_advertising = true;
    ESP_LOGI(GATTS_TABLE_TAG, "set is_advertising true: %d", is_advertising);
    size_t i = 0;
    if (name_len > 31 - 8)
    {
        ESP_LOGI(GATTS_TABLE_TAG, "name_len:%d, error",name_len);
        return ESP_FAIL;
    }
    
    raw_phone_adv_data[6] = name_len + 1;
    for (i = 0; i < name_len; i++)
    {
        raw_phone_adv_data[8 + i] = adv_dev_name[i];
    }
    //剩下的补0
    for ( i = name_len + 8; i < 31; i++)
    {
        raw_phone_adv_data[i] = 0;
    }
    esp_err_t raw_scan_ret = esp_ble_gap_config_scan_rsp_data_raw(raw_phone_scan_rsp_data, sizeof(raw_phone_scan_rsp_data));
    if (raw_scan_ret){
        ESP_LOGE(GATTS_TABLE_TAG, "config raw scan rsp data failed, error code = %x", raw_scan_ret);
    }
    esp_err_t raw_adv_ret = esp_ble_gap_config_adv_data_raw(raw_phone_adv_data, sizeof(raw_phone_adv_data));
    if (raw_adv_ret){
        ESP_LOGE(GATTS_TABLE_TAG, "config raw adv data failed, error code = %x ", raw_adv_ret);
    }else{
        ESP_LOGE(GATTS_TABLE_TAG, "config raw adv data success");
    }
    return raw_adv_ret;
}


esp_err_t notify_client(uint8_t *value, uint16_t value_len){
    esp_err_t ret = esp_ble_gatts_send_indicate(rcs_profile_tab[PROFILE_APP_IDX].gatts_if, 
                                          rcs_profile_tab[PROFILE_APP_IDX].conn_id, 
                                          rcs_handle_table[IDX_CHAR_VAL_SER_TO_CLI], 
                                          value_len, 
                                          value, 
                                          false);

    ESP_LOGE(GATTS_TABLE_TAG,"Error (%s)!\n", esp_err_to_name(ret));
    return ret;
}

esp_err_t close_server(void){
    return esp_ble_gatts_close(rcs_profile_tab[PROFILE_APP_IDX].gatts_if, 
                                rcs_profile_tab[PROFILE_APP_IDX].conn_id);
}

